"""
认证服务

提供用户认证和授权功能，包括：
- 用户注册和登录
- JWT令牌管理
- 会话管理
- 用户资料管理
"""
import hashlib
import secrets
import uuid
import base64
import json
from typing import Dict, List, Any, Optional
from datetime import datetime, timedelta
import logging

# 配置日志
logging.basicConfig(level=logging.INFO)
auth_logger = logging.getLogger('auth_service')


class AuthService:
    """认证服务类"""
    
    def __init__(self):
        # JWT密钥
        self.jwt_secret = "your-secret-key-change-in-production"
        self.jwt_algorithm = "HS256"
        self.token_expiry_hours = 24
        
        # 模拟用户数据存储
        self.users = {}
        self.sessions = {}
        self.tokens = {}
        
        # 创建一些测试用户
        self._create_test_users()
    
    def _create_test_users(self):
        """创建测试用户"""
        test_users = [
            {
                "username": "researcher_test",
                "password": "password123",
                "email": "researcher@test.com",
                "role": "researcher",
                "profile": {"name": "测试研究员", "department": "AI实验室"}
            },
            {
                "username": "integration_user",
                "password": "password123",
                "email": "integration@test.com",
                "role": "researcher",
                "profile": {"name": "集成测试用户", "department": "测试部门"}
            },
            {
                "username": "security_test_user",
                "password": "secure_password123",
                "email": "security@test.com",
                "role": "researcher",
                "profile": {"name": "安全测试用户", "department": "安全部门"}
            }
        ]
        
        for user_data in test_users:
            user_id = str(uuid.uuid4())
            self.users[user_id] = {
                "user_id": user_id,
                "username": user_data["username"],
                "password_hash": self._hash_password(user_data["password"]),
                "email": user_data["email"],
                "role": user_data["role"],
                "profile": user_data["profile"],
                "created_at": datetime.now().isoformat(),
                "last_login": None,
                "is_active": True
            }
    
    def _hash_password(self, password: str) -> str:
        """密码哈希"""
        salt = secrets.token_hex(16)
        password_hash = hashlib.pbkdf2_hmac('sha256', password.encode(), salt.encode(), 100000)
        return f"{salt}:{password_hash.hex()}"
    
    def _verify_password(self, password: str, password_hash: str) -> bool:
        """验证密码"""
        try:
            salt, stored_hash = password_hash.split(':')
            password_hash_check = hashlib.pbkdf2_hmac('sha256', password.encode(), salt.encode(), 100000)
            return password_hash_check.hex() == stored_hash
        except:
            return False
    
    def _generate_jwt_token(self, user_info: Dict[str, Any]) -> str:
        """生成简化令牌"""
        payload = {
            'user_id': user_info['user_id'],
            'username': user_info['username'],
            'role': user_info['role'],
            'exp': (datetime.utcnow() + timedelta(hours=self.token_expiry_hours)).timestamp(),
            'iat': datetime.utcnow().timestamp()
        }
        
        # 简化的令牌生成（仅用于测试）
        payload_str = json.dumps(payload, sort_keys=True)
        token_data = base64.b64encode(payload_str.encode()).decode()
        signature = hashlib.sha256((token_data + self.jwt_secret).encode()).hexdigest()[:16]
        token = f"{token_data}.{signature}"
        return token
    
    def register_user(self, username: str, password: str, email: str, 
                     role: str = "student", profile: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
        """用户注册"""
        try:
            # 检查用户名是否已存在
            for user in self.users.values():
                if user['username'] == username:
                    return {'success': False, 'error': '用户名已存在'}
                if user['email'] == email:
                    return {'success': False, 'error': '邮箱已存在'}
            
            # 创建新用户
            user_id = str(uuid.uuid4())
            user = {
                "user_id": user_id,
                "username": username,
                "password_hash": self._hash_password(password),
                "email": email,
                "role": role,
                "profile": profile or {},
                "created_at": datetime.now().isoformat(),
                "last_login": None,
                "is_active": True
            }
            
            self.users[user_id] = user
            
            auth_logger.info(f"用户注册成功: {username}")
            
            return {
                'success': True,
                'user_id': user_id,
                'message': '注册成功'
            }
            
        except Exception as e:
            auth_logger.error(f"用户注册失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }
    
    def authenticate_user(self, username: str, password: str, 
                         ip_address: str, user_agent: str) -> Dict[str, Any]:
        """用户认证"""
        try:
            # 查找用户
            user = None
            for u in self.users.values():
                if u['username'] == username:
                    user = u
                    break
            
            if not user:
                return {'success': False, 'error': '用户不存在'}
            
            if not user['is_active']:
                return {'success': False, 'error': '用户已被禁用'}
            
            # 验证密码
            if not self._verify_password(password, user['password_hash']):
                return {'success': False, 'error': '密码错误'}
            
            # 生成JWT令牌
            token = self._generate_jwt_token(user)
            
            # 创建会话
            session_id = str(uuid.uuid4())
            session = {
                'session_id': session_id,
                'user_id': user['user_id'],
                'token': token,
                'ip_address': ip_address,
                'user_agent': user_agent,
                'created_at': datetime.now().isoformat(),
                'expires_at': (datetime.now() + timedelta(hours=self.token_expiry_hours)).isoformat(),
                'is_active': True
            }
            
            self.sessions[session_id] = session
            self.tokens[token] = session_id
            
            # 更新最后登录时间
            user['last_login'] = datetime.now().isoformat()
            
            auth_logger.info(f"用户认证成功: {username}")
            
            return {
                'success': True,
                'token': token,
                'user_info': {
                    'user_id': user['user_id'],
                    'username': user['username'],
                    'email': user['email'],
                    'role': user['role'],
                    'profile': user['profile']
                },
                'expires_at': session['expires_at']
            }
            
        except Exception as e:
            auth_logger.error(f"用户认证失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }
    
    def validate_token(self, token: str) -> Dict[str, Any]:
        """验证令牌"""
        try:
            # 检查令牌是否存在
            if token not in self.tokens:
                return {'valid': False, 'error': '令牌不存在'}
            
            session_id = self.tokens[token]
            session = self.sessions.get(session_id)
            
            if not session or not session['is_active']:
                return {'valid': False, 'error': '会话无效'}
            
            # 验证简化令牌
            try:
                token_parts = token.split('.')
                if len(token_parts) != 2:
                    return {'valid': False, 'error': '令牌格式无效'}
                
                token_data, signature = token_parts
                expected_signature = hashlib.sha256((token_data + self.jwt_secret).encode()).hexdigest()[:16]
                
                if signature != expected_signature:
                    return {'valid': False, 'error': '令牌签名无效'}
                
                payload_str = base64.b64decode(token_data.encode()).decode()
                payload = json.loads(payload_str)
                
                # 检查过期时间
                if datetime.utcnow().timestamp() > payload['exp']:
                    return {'valid': False, 'error': '令牌已过期'}
                    
            except Exception:
                return {'valid': False, 'error': '令牌解析失败'}
            
            # 获取用户信息
            user = self.users.get(payload['user_id'])
            if not user or not user['is_active']:
                return {'valid': False, 'error': '用户无效'}
            
            return {
                'valid': True,
                'user_info': {
                    'user_id': user['user_id'],
                    'username': user['username'],
                    'email': user['email'],
                    'role': user['role'],
                    'profile': user['profile']
                }
            }
            
        except Exception as e:
            auth_logger.error(f"令牌验证失败: {str(e)}")
            return {
                'valid': False,
                'error': str(e)
            }
    
    def revoke_token(self, token: str) -> Dict[str, Any]:
        """撤销令牌"""
        try:
            if token not in self.tokens:
                return {'success': False, 'error': '令牌不存在'}
            
            session_id = self.tokens[token]
            session = self.sessions.get(session_id)
            
            if session:
                session['is_active'] = False
                session['revoked_at'] = datetime.now().isoformat()
            
            del self.tokens[token]
            
            auth_logger.info("令牌撤销成功")
            
            return {
                'success': True,
                'message': '令牌撤销成功'
            }
            
        except Exception as e:
            auth_logger.error(f"令牌撤销失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }
    
    def update_user_profile(self, user_id: str, profile_data: Dict[str, Any]) -> Dict[str, Any]:
        """更新用户资料"""
        try:
            if user_id not in self.users:
                return {'success': False, 'error': '用户不存在'}
            
            user = self.users[user_id]
            
            # 更新允许的字段
            allowed_fields = ['profile', 'email']
            for field in allowed_fields:
                if field in profile_data:
                    if field == 'profile':
                        user['profile'].update(profile_data[field])
                    else:
                        user[field] = profile_data[field]
            
            user['updated_at'] = datetime.now().isoformat()
            
            auth_logger.info(f"用户资料更新成功: {user_id}")
            
            return {
                'success': True,
                'message': '资料更新成功'
            }
            
        except Exception as e:
            auth_logger.error(f"用户资料更新失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }
    
    def get_user_info(self, user_id: str) -> Dict[str, Any]:
        """获取用户信息"""
        try:
            if user_id not in self.users:
                return {'success': False, 'error': '用户不存在'}
            
            user = self.users[user_id]
            
            return {
                'success': True,
                'user': {
                    'user_id': user['user_id'],
                    'username': user['username'],
                    'email': user['email'],
                    'role': user['role'],
                    'profile': user['profile'],
                    'created_at': user['created_at'],
                    'last_login': user['last_login']
                }
            }
            
        except Exception as e:
            auth_logger.error(f"获取用户信息失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }
    
    def list_active_sessions(self, user_id: str) -> Dict[str, Any]:
        """列出用户的活跃会话"""
        try:
            user_sessions = [
                {
                    'session_id': session['session_id'],
                    'ip_address': session['ip_address'],
                    'user_agent': session['user_agent'],
                    'created_at': session['created_at'],
                    'expires_at': session['expires_at']
                }
                for session in self.sessions.values()
                if session['user_id'] == user_id and session['is_active']
            ]
            
            return {
                'success': True,
                'sessions': user_sessions,
                'count': len(user_sessions)
            }
            
        except Exception as e:
            auth_logger.error(f"获取会话列表失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }
    
    def change_password(self, user_id: str, old_password: str, new_password: str) -> Dict[str, Any]:
        """修改密码"""
        try:
            if user_id not in self.users:
                return {'success': False, 'error': '用户不存在'}
            
            user = self.users[user_id]
            
            # 验证旧密码
            if not self._verify_password(old_password, user['password_hash']):
                return {'success': False, 'error': '旧密码错误'}
            
            # 设置新密码
            user['password_hash'] = self._hash_password(new_password)
            user['password_changed_at'] = datetime.now().isoformat()
            
            auth_logger.info(f"密码修改成功: {user_id}")
            
            return {
                'success': True,
                'message': '密码修改成功'
            }
            
        except Exception as e:
            auth_logger.error(f"密码修改失败: {str(e)}")
            return {
                'success': False,
                'error': str(e)
            }
    
    def get_service_status(self) -> Dict[str, Any]:
        """获取服务状态"""
        active_sessions = len([s for s in self.sessions.values() if s['is_active']])
        
        return {
            'service_name': 'AuthService',
            'status': 'running',
            'users_count': len(self.users),
            'active_sessions_count': active_sessions,
            'total_sessions_count': len(self.sessions),
            'active_tokens_count': len(self.tokens),
            'last_activity': datetime.now().isoformat()
        }